import socket
import platform
import sys

import cv2
import numpy as np

import highPassFilter, convertHSI, PseudoColorEnhancement, gray_scale_transform, DFT, median_and_average_filter,sobel,hough,threshold_segment,image_recover
import qdarkstyle
from PyQt5.QtCore import Qt, QTimer, QDateTime, QDate, QFile
from PyQt5.QtGui import QPalette, QColor, QIntValidator, QImage, QPixmap
from PyQt5.QtWidgets import (QApplication, QWidget, QMainWindow, QPushButton, QTextEdit,
                             QGroupBox, QCheckBox, QRadioButton, QComboBox, QLabel,
                             QVBoxLayout, QHBoxLayout, QGridLayout, QStyleFactory,
                             QTabWidget, QSizePolicy, QProgressBar, QTableWidget,
                             QLineEdit, QSpinBox, QDateTimeEdit, QSlider,
                             QScrollBar, QMenu, QMenuBar, QAction, QCalendarWidget, QDial, QFileDialog, QMessageBox)

ip_address = socket.gethostbyname(socket.gethostname())
operating_system = platform.platform()


# 滑动条控件构造类
class MySlider(QSlider):
    def __init__(self, min=0, max=100, val=50, diretion=Qt.Horizontal, name="test"):
        super().__init__(diretion)
        self.setMinimum(min)
        self.setMaximum(max)
        self.setValue(val)


# 标记控制窗口
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        # 应用的初始调色板
        self.origPalette = QApplication.palette()
        self.initUi()
        self.rawImage = None
        self.transformImage = None
        self.newImage = None  # 暂存图像使用
        self.img_dft = None  # 暂存图像DFT结果使用
        self.blur_kernel = None  # 构造模糊图像后储存模糊核

    def initUi(self):
        """
        初始化主页面
        :return: null
        """
        # 生成菜单栏
        self.initMenuBar()

        self.mainLayout = QGridLayout()
        self.mainLayout.setSpacing(10)

        self.rawImageLabel = QLabel('原始图像')
        self.rawImageLabel.resize(512, 512)
        self.mainLayout.addWidget(self.rawImageLabel, 0, 0)

        self.transformImageLabel = QLabel('转换后图像')
        self.transformImageLabel.resize(512, 512)
        self.mainLayout.addWidget(self.transformImageLabel, 0, 1)

        # self.parameterLayout = QGridLayout()
        # self.parameterLayout.resize(512, 512)
        # self.parameterWidget = QWidget()
        # self.parameterWidget.setLayout(self.parameterLayout)
        # self.mainLayout.addWidget(self.parameterWidget, 0, 3)

        mainWidget = QWidget()
        mainWidget.setLayout(self.mainLayout)
        self.setCentralWidget(mainWidget)

    # 菜单栏设置
    def initMenuBar(self):
        mBar = self.menuBar()
        # 文件菜单
        menuFile = mBar.addMenu('文件(&F)')
        aOpen = QAction('打开图片(&O)', self)
        aOpen.triggered.connect(self.loadImage)
        aSwap = QAction('将生成图片做进一步变换', self)
        aSwap.triggered.connect(self.swapImage)
        aSave = QAction('保存图片(&S)', self)
        aSave.triggered.connect(self.saveImage)
        aExit = QAction('退出(&X)', self)
        aExit.triggered.connect(self.close)
        menuFile.addActions([aOpen, aSave, aSwap, aExit])

        # 预变换菜单
        menuImagePreprocess = mBar.addMenu('图像预变换')
        aToGray = QAction('转换为灰度图', self)
        aToGray.triggered.connect(self.toGrayImage)
        aTranslation = QAction('图像平移', self)
        aTranslation.triggered.connect(self.translationImage)
        aRotate = QAction('图像旋转', self)
        aRotate.triggered.connect(self.rotateImage)
        aSaltAndPepperNoise = QAction('添加椒盐噪声', self)
        aSaltAndPepperNoise.triggered.connect(self.addSaltAndPepperNoise)
        aGaussianNoise = QAction('添加高斯噪声', self)
        aBlur = QAction('图像模糊', self)
        aBlur.triggered.connect(self.blurImage)
        aGaussianNoise.triggered.connect(self.addGaussianNoise)
        aHistogramShow = QAction('计算图像直方图', self)
        aHistogramShow.triggered.connect(self.show_histogram)
        menuImagePreprocess.addActions([aToGray, aTranslation, aRotate, aSaltAndPepperNoise, aGaussianNoise, aBlur, aHistogramShow])

        # 图像变换菜单
        menuImageTransform = mBar.addMenu('图像变换(&T)')
        aFourierTransform = QAction('图像傅里叶变换(&F)', self)
        aFourierTransform.triggered.connect(self.dft_spectrum)
        aInversionFourierTransform = QAction('图像傅里叶逆变换(&I)', self)
        aInversionFourierTransform.triggered.connect(self.idft_spectrum)
        menuImageTransform.addActions([aFourierTransform, aInversionFourierTransform])

        # 图像增强菜单
        menuImageEnhancement = mBar.addMenu('图像增强(&E)')
        aHistogramEqualization = QAction('直方图均衡化', self)
        aHistogramEqualization.triggered.connect(self.histogram_equalization)
        aLinerGrayLevelTransform = QAction('全局线性灰度拉伸', self)
        aLinerGrayLevelTransform.triggered.connect(self.global_graylevel_transform)
        aMedianFilter = QAction('中值滤波', self)
        aMedianFilter.triggered.connect(self.MedianFilter)
        aAverageFilter = QAction('均值滤波', self)
        aAverageFilter.triggered.connect(self.AverageFilter)
        menuImageEnhancement.addActions([aHistogramEqualization, aLinerGrayLevelTransform,
                                         aMedianFilter, aAverageFilter])

        # 图像锐化菜单
        menuImageSharpening = mBar.addMenu('图像锐化(&S)')
        aHighPassEdgeEnhancement = QAction('使用高通模板进行边缘锐化', self)
        aHighPassEdgeEnhancement.triggered.connect(self.highPassEnhancement)
        aHSIEnhancement = QAction('在HSI颜色空间下调整图像', self)
        aHSIEnhancement.triggered.connect(self.adjust_hsi_space)
        aPseudoColorEnhancement = QAction('对灰度图像做伪彩色增强', self)
        aPseudoColorEnhancement.triggered.connect(self.pseudoColorEnhancement)
        menuImageSharpening.addActions([aHighPassEdgeEnhancement, aHSIEnhancement, aPseudoColorEnhancement])

        # 图像分割菜单
        menuImageSegment = mBar.addMenu('图像分割(&C)')
        aFixThresholdSegment = QAction('固定阈值分割', self)
        aFixThresholdSegment.triggered.connect(self.fixed_segment)
        aOTSU = QAction('大津阈值分割', self)
        aOTSU.triggered.connect(self.otsu_segment)
        aSobel = QAction('使用Sobel算子进行边缘检测', self)
        aSobel.triggered.connect(self.sobel_edge_detection)
        aPrewitt = QAction('使用Prewitt算子进行边缘检测', self)
        aPrewitt.triggered.connect(self.prewitt_edge_detection)
        aHoughLine = QAction('使用Hough变换检测图像中直线', self)
        aHoughLine.triggered.connect(self.hough_line_detection)
        menuImageSegment.addActions([aFixThresholdSegment, aOTSU, aSobel, aPrewitt, aHoughLine])

        # 图像复原菜单
        menuImageRestoration = mBar.addMenu('图像复原(&R)')
        aWiener = QAction('使用维纳滤波复原', self)
        aWiener.triggered.connect(self.wienerRecovery)
        aReverse = QAction('使用逆滤波复原', self)
        aReverse.triggered.connect(self.reverseRecovery)
        menuImageRestoration.addActions([aWiener, aReverse])

        # 关于菜单
        menuAbout = mBar.addMenu('关于(&A)')
        aAbout = QAction('软件信息', self)
        aAbout.triggered.connect(self.show_about)
        menuAbout.addActions([aAbout])

    def showImage(self, aimed_label, img_array):
        """
        将传入的ndarray格式图像显示在指定label中
        :param aimed_label:要显示图像的label控件
        :param img_array: numpy格式图像，数据类型uint8，数据范围0~255, 形状H*W*3，通道顺序RGB，或形状H*W,单通道灰度图
        :return: None
        """
        if img_array is None:
            return
        # 这里一定要注意QT内图片的顺序是W*H
        if len(img_array.shape) == 3 and img_array.shape[2] == 3:
            # 显示三通道RGB
            new_image = QImage(img_array.data, img_array.shape[1], img_array.shape[0], QImage.Format_RGB888)
            aimed_label.setPixmap(QPixmap.fromImage(new_image))
        elif len(img_array.shape) == 2:
            # 显示单通道灰度图
            new_image = QImage(img_array.data, img_array.shape[1], img_array.shape[0], QImage.Format_Grayscale8)
            aimed_label.setPixmap(QPixmap.fromImage(new_image))

    def loadImage(self):
        """
        菜单栏”打开图像“功能的回调函数，显示打开文件对话框，返回读入的图片并显示图片
        :return: numpy格式图像，数据类型uint8，数据范围0~255，形状H*W*C，通道顺序RGB，或单通道灰度图
        """
        image_path = QFileDialog.getOpenFileName(self, "打开图片", "./",
                                                 "JPG Files (*.jpg);;JPEG Files (*.jpeg);;PNG Files (*.png);;BMP Files "
                                                 "(*.bmp);;TIF Files (*.tif)")[0]
        if len(image_path) != 0:
            print("打开图像：" + image_path)
            src = cv2.imread(image_path)
            if src is None:
                QMessageBox.warning(self, "警告", "图像打开失败！\n请确保图像路径不包含中文！\n请选择三通道RGB图或单通道灰度图\n其他图像本工具箱无法处理")
                return
            print("打开图像的维度为：" + str(src.shape))
            if len(src.shape) == 3 and src.shape[2] == 3:
                # 若打开三通道图像，则转换图像通道顺序为RGB
                src = cv2.cvtColor(src, cv2.COLOR_BGR2RGB)
                self.rawImage = src
                self.showImage(self.rawImageLabel, self.rawImage)
                return src
            elif len(src.shape) == 2:
                # 若打开灰度图像则直接显示
                self.rawImage = src
                self.showImage(self.rawImageLabel, self.rawImage)
                return src
            else:
                QMessageBox.warning(self, "警告", "请选择三通道RGB图或单通道灰度图\n其他图像本工具箱无法处理")
                return

    def saveImage(self):
        """
        菜单栏“保存图像"功能的回调函数，打开保存文件对话框，将self.transformImage保存到用户选定的位置
        :return: None
        """
        if self.transformImage is None:
            QMessageBox.warning(self, "警告", "无生成的图片\n无法执行命令")
            return
        imagePath = QFileDialog.getSaveFileName(self, "保存图片", "./",
                                                "JPG Files (*.jpg);;JPEG Files (*.jpeg);;PNG Files (*.png);;BMP Files "
                                                "(*.bmp)")[0]
        if len(self.transformImage.shape) == 3:
            cv2.imwrite(imagePath, cv2.cvtColor(self.transformImage, cv2.COLOR_RGB2BGR))
        else:
            cv2.imwrite(imagePath, self.transformImage)

    def swapImage(self):
        """
        菜单栏"将生成图片做进一步变换"选项回调函数
        将self.transformImage复制一份备份到self.rawImage并显示
        :return: None
        """
        if self.transformImage is None:
            QMessageBox.warning(self, "警告", "无生成的图片\n无法执行命令")
            return
        # 将变换图像复制到待操作图像并显示
        self.rawImage = self.transformImage.copy()
        self.showImage(self.rawImageLabel, self.rawImage)
        # 清除变换图像
        self.transformImage = None
        self.transformImageLabel.setPixmap(QPixmap(""))
        print("当前待操作图像的维度为：" + str(self.rawImage.shape))

    def toGrayImage(self):
        """
        菜单栏"图像预变换——转换为灰度图"选项回调函数
        :return: None
        """
        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开图片\n无法执行命令")
            return
        if len(self.rawImage.shape) == 3 and self.rawImage.shape[2] == 3:
            self.rawImage = cv2.cvtColor(self.rawImage, cv2.COLOR_RGB2GRAY)
            print("转换后图像形状为：" + str(self.rawImage.shape))
            self.showImage(self.rawImageLabel, self.rawImage)
        else:
            QMessageBox.warning(self, "警告", "当前图片形状为：%s 不为(H*W*3)\n无法执行命令" % str(self.rawImage.shape))
            return

    def translationImage(self):
        """
        菜单栏”图像预变换——图像平移“选项回调函数
        :return:
        """

        # 按下确认按钮后，新图像复制到原图像位置上并销毁工具栏
        def remove_tools():
            self.rawImage = self.newImage.copy()
            self.showImage(self.rawImageLabel, self.rawImage)
            tools_widget.setParent(None)

        # 进度条变化的回调函数 执行图像平移
        def do_move_image():
            deltah = h_slider.value()
            deltaw = w_slider.value()
            # print(deltah, deltaw)
            self.newImage = self.rawImage.copy()
            temp = self.rawImage.copy()
            if len(self.rawImage.shape) == 2:
                if deltaw != 0:
                    temp[:, 0:deltaw] = self.rawImage[:, w - deltaw:w]
                    temp[:, deltaw:w] = self.rawImage[:, 0:w - deltaw]
                if deltah != 0:
                    self.newImage[0:deltah, :] = temp[h - deltah:h, :]
                    self.newImage[deltah:h, :] = temp[0:h - deltah, :]
            elif len(self.rawImage.shape) == 3:
                if deltaw != 0:
                    temp[:, 0:deltaw, :] = self.rawImage[:, w - deltaw:w, :]
                    temp[:, deltaw:w, :] = self.rawImage[:, 0:w - deltaw, :]
                if deltah != 0:
                    self.newImage[0:deltah, :, :] = temp[h - deltah:h, :, :]
                    self.newImage[deltah:h, :, :] = temp[0:h - deltah, :, :]
            self.showImage(self.rawImageLabel, self.newImage)

        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return
        if len(self.rawImage.shape) == 2:
            h, w = self.rawImage.shape
        else:
            h, w, _ = self.rawImage.shape

        tools_widget = QWidget()
        tools_layout = QGridLayout()
        tools_layout.setSpacing(10)
        h_slider = MySlider(min=0, max=h, val=0)
        w_slider = MySlider(min=0, max=w, val=0)
        btn = QPushButton("调整完毕")

        h_slider.valueChanged.connect(do_move_image)
        w_slider.valueChanged.connect(do_move_image)
        btn.clicked.connect(remove_tools)

        tools_layout.addWidget(h_slider, 0, 0)
        tools_layout.addWidget(w_slider, 1, 0)
        tools_layout.addWidget(btn, 2, 0)
        tools_widget.setLayout(tools_layout)
        self.mainLayout.addWidget(tools_widget, 0, 3)

    def rotateImage(self):
        """
        菜单栏”图像预变换——图像旋转“选项回调函数
        :return: None
        """

        # 按下确认按钮后，新图像复制到原图像位置上并销毁工具栏
        def remove_tools():
            self.rawImage = self.newImage.copy()
            self.showImage(self.rawImageLabel, self.rawImage)
            tools_widget.setParent(None)

        # 进度条变化的回调函数 执行图像旋转
        def do_rotate_image():
            delta_degree = degree_slider.value()
            self.newImage = self.rawImage.copy()
            center = (w // 2, h // 2)
            M = cv2.getRotationMatrix2D(center, delta_degree, 1.0)  # 12
            self.newImage = cv2.warpAffine(self.rawImage, M, (w, h))  # 13
            self.showImage(self.rawImageLabel, self.newImage)

        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return
        if len(self.rawImage.shape) == 2:
            h, w = self.rawImage.shape
        else:
            h, w, _ = self.rawImage.shape

        tools_widget = QWidget()
        tools_layout = QGridLayout()
        tools_layout.setSpacing(10)
        degree_slider = MySlider(min=0, max=360, val=0)
        btn = QPushButton("调整完毕")

        degree_slider.valueChanged.connect(do_rotate_image)
        btn.clicked.connect(remove_tools)

        tools_layout.addWidget(degree_slider, 0, 0)
        tools_layout.addWidget(btn, 1, 0)
        tools_widget.setLayout(tools_layout)
        self.mainLayout.addWidget(tools_widget, 0, 3)

    def blurImage(self):

        # 按下确认按钮后，新图像复制到原图像位置上并销毁工具栏
        def remove_tools():
            self.rawImage = self.newImage.copy()
            self.showImage(self.rawImageLabel, self.rawImage)
            tools_widget.setParent(None)

        # 进度条变化的回调函数 执行图像模糊
        def do_blur_image():
            degree = degree_slider.value()
            angle = angle_slider.value()
            self.newImage, self.blur_kernel = image_recover.blurTool(self.rawImage, degree, angle)
            self.showImage(self.rawImageLabel, self.newImage)

        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return
        if not len(self.rawImage.shape) == 2:
            QMessageBox.warning(self, "警告", "当前图片形状为：%s 不为(H*W)\n无法执行命令" % str(self.rawImage.shape))
            return

        tools_widget = QWidget()
        tools_layout = QGridLayout()
        tools_layout.setSpacing(10)
        degree_slider = MySlider(min=1, max=50, val=20)
        angle_slider = MySlider(min=1, max=350, val=30)
        btn = QPushButton("调整完毕")

        degree_slider.valueChanged.connect(do_blur_image)
        angle_slider.valueChanged.connect(do_blur_image)
        btn.clicked.connect(remove_tools)

        tools_layout.addWidget(degree_slider, 0, 0)
        tools_layout.addWidget(angle_slider, 1, 0)
        tools_layout.addWidget(btn, 2, 0)
        tools_widget.setLayout(tools_layout)
        self.mainLayout.addWidget(tools_widget, 0, 3)

        do_blur_image()

    def addSaltAndPepperNoise(self):
        """
        菜单栏”图像预变换——添加椒盐噪声“选项回调函数
        :return:
        """

        # 按下确认按钮后，新图像复制到目标图像位置上并销毁工具栏
        def remove_tools():
            self.rawImage = self.newImage.copy()
            self.showImage(self.rawImageLabel, self.rawImage)
            tools_widget.setParent(None)

        # 进度条变化的回调函数 执行图像旋转
        def do_noise_image():
            percent_noise = percent_slider.value()/100.0
            self.newImage = self.rawImage.copy()
            self.newImage = median_and_average_filter.SaltAndPepperNoise(self.rawImage, percent_noise)
            self.showImage(self.rawImageLabel, self.newImage)

        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return

        tools_widget = QWidget()
        tools_layout = QGridLayout()
        tools_layout.setSpacing(10)
        percent_slider = MySlider(min=0, max=80, val=5)
        btn = QPushButton("调整完毕")

        percent_slider.valueChanged.connect(do_noise_image)
        btn.clicked.connect(remove_tools)

        tools_layout.addWidget(percent_slider, 0, 0)
        tools_layout.addWidget(btn, 1, 0)
        tools_widget.setLayout(tools_layout)
        self.mainLayout.addWidget(tools_widget, 0, 3)
        do_noise_image()

    def addGaussianNoise(self):
        """
        菜单栏”图像预变换——添加高斯噪声“选项回调函数
        :return:
        """

        # 按下确认按钮后，新图像复制到目标图像位置上并销毁工具栏
        def remove_tools():
            self.rawImage = self.newImage.copy()
            self.showImage(self.rawImageLabel, self.rawImage)
            tools_widget.setParent(None)

        # 进度条变化的回调函数 执行图像旋转
        def do_noise_image():
            gaussian_scale = scale_slider.value()
            self.newImage = self.rawImage.copy()
            self.newImage = median_and_average_filter.GaussianNoise(self.rawImage, gaussian_scale)
            self.showImage(self.transformImageLabel, self.newImage)

        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return

        tools_widget = QWidget()
        tools_layout = QGridLayout()
        tools_layout.setSpacing(10)
        scale_slider = MySlider(min=1, max=10, val=3)
        btn = QPushButton("调整完毕")

        scale_slider.valueChanged.connect(do_noise_image)
        btn.clicked.connect(remove_tools)

        tools_layout.addWidget(scale_slider, 0, 0)
        tools_layout.addWidget(btn, 1, 0)
        tools_widget.setLayout(tools_layout)
        self.mainLayout.addWidget(tools_widget, 0, 3)
        do_noise_image()

    def dft_spectrum(self):
        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开图片\n无法执行命令")
            return
        if not len(self.rawImage.shape) == 2:
            QMessageBox.warning(self, "警告", "当前图片形状为：%s 不为(H*W)\n无法执行命令" % str(self.rawImage.shape))
            return
        self.transformImage, self.img_dft = DFT.dft_tool(self.rawImage)
        self.showImage(self.transformImageLabel, self.transformImage)

    def idft_spectrum(self):
        if self.img_dft is None:
            QMessageBox.warning(self, "警告", "未对任何图片做离散傅里叶变换\n无法执行逆变换命令")
            return
        self.transformImage = DFT.idft_tool(self.img_dft)
        self.showImage(self.transformImageLabel, self.transformImage)

    def show_histogram(self):
        """
        菜单栏"图像增强——显示图像直方图"选项回调函数 注意当处理彩色图像时，将自动换化为HSI空间后在I通道计算直方图
        :return:
        """
        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return
        if len(self.rawImage.shape) == 3 and self.rawImage.shape[2] == 3:
            # 对彩色图像将在HSI空间处理I通道，特别提醒用户
            QMessageBox.warning(self, "提示", "当前图片形状为：%s 是彩色图像或三通道相同的灰度图像\n将自动换化为HSI空间后在I通道计算直方图" % str(self.rawImage.shape))
        self.newImage = gray_scale_transform.make_histogram(self.rawImage, return_numpy=True)
        print(self.newImage.shape)
        self.showImage(self.transformImageLabel, self.newImage)

    def histogram_equalization(self):
        """
        菜单栏"图像增强——直方图均衡化"选项回调函数 注意当处理彩色图像时，将自动换化为HSI空间后在I通道执行直方图均衡化，再转换回RGB
        :return: None
        """
        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return
        if len(self.rawImage.shape) == 3 and self.rawImage.shape[2] == 3:
            # 对彩色图像将在HSI空间处理I通道，特别提醒用户
            QMessageBox.warning(self, "提示", "当前图片形状为：%s 是彩色图像或三通道相同的灰度图像\n将自动换化为HSI空间后在I通道执行直方图均衡化" % str(self.rawImage.shape))
        self.transformImage = gray_scale_transform.histogram_equalization(self.rawImage)
        self.showImage(self.transformImageLabel, self.transformImage)

    def global_graylevel_transform(self):
        if self.rawImage is None:
            return
        self.transformImage = gray_scale_transform.global_linear_transform(self.rawImage)
        self.showImage(self.transformImageLabel, self.transformImage)

    def AverageFilter(self):
        """
        菜单栏”图像增强——均值滤波“选项回调函数
        :return:
        """
        if self.rawImage is None:
            return
        self.transformImage = median_and_average_filter.average_filter(self.rawImage)
        self.showImage(self.transformImageLabel, self.transformImage)

    def MedianFilter(self):
        """
        菜单栏”图像增强——中值滤波“选项回调函数
        :return:
        """
        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return
        self.transformImage = median_and_average_filter.median_filter(self.rawImage)
        self.showImage(self.transformImageLabel, self.transformImage)

    def highPassEnhancement(self):

        # 按下确认按钮后，新图像复制到目标图像位置上并销毁工具栏
        def remove_tools():
            self.transformImage = self.newImage.copy()
            self.showImage(self.transformImageLabel, self.transformImage)
            tools_widget.setParent(None)

        # 单选框按下的回调函数
        def do_high_pass_enhancement():
            if bcore1.isChecked():
                core = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]])
            elif bcore2.isChecked():
                core = np.array([[0, -1, 0], [-1, 4, -1], [0, -1, 0]])
            elif bcore3.isChecked():
                core = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]])
            elif bcore4.isChecked():
                core = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])
            elif bcore5.isChecked():
                core = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
            elif bcore6.isChecked():
                core = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])

            self.newImage = highPassFilter.edgeEnhancement(src=self.rawImage, core=core, alpha=0.05)
            self.showImage(self.transformImageLabel, self.newImage)

        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return

        tools_widget = QWidget()
        tools_layout = QGridLayout()
        tools_layout.setSpacing(10)
        bcore1 = QRadioButton("[0, 1, 0], [1, -4, 1], [0, 1, 0]")
        bcore2 = QRadioButton("[0, -1, 0], [-1, 4, -1], [0, -1, 0]")
        bcore3 = QRadioButton("[1, 1, 1], [1, -8, 1], [1, 1, 1]")
        bcore4 = QRadioButton("[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]")
        bcore5 = QRadioButton("[-1, -2, -1], [0, 0, 0], [1, 2, 1]")
        bcore6 = QRadioButton("[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]")
        btn = QPushButton("调整完毕")

        bcore1.toggled.connect(do_high_pass_enhancement)
        bcore2.toggled.connect(do_high_pass_enhancement)
        bcore3.toggled.connect(do_high_pass_enhancement)
        bcore4.toggled.connect(do_high_pass_enhancement)
        bcore5.toggled.connect(do_high_pass_enhancement)
        bcore6.toggled.connect(do_high_pass_enhancement)
        btn.clicked.connect(remove_tools)

        tools_layout.addWidget(bcore1, 0, 0)
        tools_layout.addWidget(bcore2, 1, 0)
        tools_layout.addWidget(bcore3, 2, 0)
        tools_layout.addWidget(bcore4, 3, 0)
        tools_layout.addWidget(bcore5, 4, 0)
        tools_layout.addWidget(bcore6, 5, 0)
        tools_layout.addWidget(btn, 6, 0)
        tools_widget.setLayout(tools_layout)
        self.mainLayout.addWidget(tools_widget, 0, 3)

    def adjust_hsi_space(self):
        def removeHSITools():
            tools_widget.setParent(None)
            self.transformImage = self.newImage.copy()
            self.showImage(self.transformImageLabel, self.transformImage)

        def do_hsi_enhancement():
            times_h = 2 * h_slider.value() / 100
            times_s = 2 * s_slider.value() / 100
            times_i = 2 * i_slider.value() / 100

            h, s, i = convertHSI.rgb2hsi(self.rawImage.copy())
            h = np.clip(h * times_h, 0, 1)
            s = np.clip(s * times_s, 0, 1)
            i = np.clip(i * times_i, 0, 1)
            self.newImage = convertHSI.hsi2rgb(np.stack((h, s, i), axis=2))
            self.showImage(self.transformImageLabel, self.newImage)

        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return
        if not (len(self.rawImage.shape) == 3 and self.rawImage.shape[2] == 3):
            # 确保只对彩色图像执行操作
            QMessageBox.warning(self, "警告", "当前图片形状为：%s 不为(H*W*3)\n无法执行命令" % str(self.rawImage.shape))
            return

        tools_widget = QWidget()
        tools_layout = QGridLayout()
        tools_layout.setSpacing(10)
        h_slider = MySlider()
        s_slider = MySlider()
        i_slider = MySlider()
        btn1 = QPushButton("调整完毕")
        h_slider.valueChanged.connect(do_hsi_enhancement)
        s_slider.valueChanged.connect(do_hsi_enhancement)
        i_slider.valueChanged.connect(do_hsi_enhancement)
        btn1.clicked.connect(removeHSITools)
        tools_layout.addWidget(h_slider, 0, 0)
        tools_layout.addWidget(s_slider, 1, 0)
        tools_layout.addWidget(i_slider, 2, 0)
        tools_layout.addWidget(btn1, 3, 0)
        tools_widget.setLayout(tools_layout)
        self.mainLayout.addWidget(tools_widget, 0, 3)
        self.showImage(self.transformImageLabel, self.rawImage)

    def pseudoColorEnhancement(self):
        """
        菜单栏”图像增强——伪彩色增强“选项回调函数，只适用于灰度图像
        :return:
        """
        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开图片\n无法执行命令")
            return
        if not len(self.rawImage.shape) == 2:
            QMessageBox.warning(self, "警告", "当前图片形状为：%s 不为(H*W*3)\n无法执行命令" % str(self.rawImage.shape))
            return
        self.transformImage = PseudoColorEnhancement.doPseudoColorEnhance(self.rawImage)
        self.showImage(self.transformImageLabel, self.transformImage)

    def fixed_segment(self):
        def removeHSITools():
            tools_widget.setParent(None)
            self.transformImage = self.newImage.copy()
            self.showImage(self.transformImageLabel, self.transformImage)

        def do_fixed_segment():
            threshold = threshold_slider.value()
            self.newImage = threshold_segment.do_segment(self.rawImage, threshold)
            self.showImage(self.transformImageLabel, self.newImage)

        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return
        if not len(self.rawImage.shape) == 2:
            QMessageBox.warning(self, "警告", "当前图片形状为：%s 不为(H*W)\n无法执行命令" % str(self.rawImage.shape))
            return

        tools_widget = QWidget()
        tools_layout = QGridLayout()
        tools_layout.setSpacing(10)
        threshold_slider = MySlider(0, 255, 125)
        btn1 = QPushButton("调整完毕")
        threshold_slider.valueChanged.connect(do_fixed_segment)
        btn1.clicked.connect(removeHSITools)
        tools_layout.addWidget(threshold_slider, 0, 0)
        tools_layout.addWidget(btn1, 1, 0)
        tools_widget.setLayout(tools_layout)
        self.mainLayout.addWidget(tools_widget, 0, 3)
        self.showImage(self.transformImageLabel, self.rawImage)
        do_fixed_segment()

    def otsu_segment(self):
        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开任何图片\n无法执行")
            return
        if not len(self.rawImage.shape) == 2:
            QMessageBox.warning(self, "警告", "当前图片形状为：%s 不为(H*W)\n无法执行命令" % str(self.rawImage.shape))
            return
        otsu = threshold_segment.OTSU_enhance(self.rawImage)
        self.transformImage = threshold_segment.do_segment(self.rawImage, otsu)
        self.showImage(self.transformImageLabel, self.transformImage)

    def sobel_edge_detection(self):
        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开图片\n无法执行命令")
            return
        _, _, self.transformImage = sobel.edge_detection(self.rawImage, method='sobel')
        self.showImage(self.transformImageLabel, self.transformImage)

    def prewitt_edge_detection(self):
        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开图片\n无法执行命令")
            return
        _, _, self.transformImage = sobel.edge_detection(self.rawImage, method='prewitt')
        self.showImage(self.transformImageLabel, self.transformImage)

    def hough_line_detection(self):
        if self.rawImage is None:
            QMessageBox.warning(self, "警告", "未打开图片\n无法执行命令")
            return
        self.transformImage = hough.hough_tool(self.rawImage)
        self.showImage(self.transformImageLabel, self.transformImage)

    def wienerRecovery(self):
        if self.blur_kernel is None:
            QMessageBox.warning(self, "警告", "未对任何图片做模糊处理\n无法执行恢复命令")
            return
        self.transformImage = image_recover.wienerTools(self.rawImage, self.blur_kernel)
        self.showImage(self.transformImageLabel, self.transformImage)

    def reverseRecovery(self):
        if self.blur_kernel is None:
            QMessageBox.warning(self, "警告", "未对任何图片做模糊处理\n无法执行恢复命令")
            return
        self.transformImage = image_recover.reverseTools(self.rawImage,self.blur_kernel)
        self.showImage(self.transformImageLabel, self.transformImage)

    def show_about(self):
        QMessageBox.about(self, "关于", "BUAA数字图像处理课程综合实验平台\nAuthor:孟亚鹏 胡宇轩 李培烁\n2021.10.21")


# if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyleSheet(qdarkstyle.load_stylesheet())

window = MainWindow()

window.resize(1650, 512)
window.setWindowTitle('Comprehensive Experimental Platen for Digital Image Processing')
window.show()
sys.exit(app.exec_())
